﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using Expressionista.Extensions.Strings;
using Expressionista.UserControls;
using Expressionista.Dialogs;

namespace Expressionista
{
	/// <summary>
	/// Interaction logic for Window1.xaml
	/// </summary>
	public partial class Window1 : Window
	{
		private const string SettingsFilepath = "settings.xml";
		public Window1()
		{
			InitializeComponent();
		}

		private void MatchBTN_Click(object sender, RoutedEventArgs e)
		{
			if (string.IsNullOrEmpty(SourceV.TextBox.Text))
			{
				MessageBox.Show("Cannot process Regex without source text to parse.", "Error");
				return;
			}

			Regex re = null;


			try
			{
				MatchesV.SetMatches(RegexV.RegexString, RegexV.RegexOptions, SourceV.TextBox.Text);
			}
			catch (Exception ex)
			{
				MessageBox.Show(string.Format("Error parsing Regex: {0}", ex), "Error");
			}
		}

		private void ToCSBTN_Click(object sender, RoutedEventArgs e)
		{
			statusBar.Items.Clear();
			string regexStr = getCSharpCodeFromRegex(RegexV.RegexString, RegexV.RegexOptions);
			if (string.IsNullOrEmpty(regexStr))
			{
				statusBar.Items.Add("Could not convert Regex to C#.");
				return;
			}
			Clipboard.SetText(regexStr);
			statusBar.Items.Add("C# code copied to the clipboard!");
		}

		

		private string getOptionsAsString(Regex regex)
		{
			List<string> options = new List<string>();


			if ((regex.Options & RegexOptions.IgnoreCase) == RegexOptions.IgnoreCase)
			{
				options.Add("RegexOptions.IgnoreCase");
			}

			if ((regex.Options & RegexOptions.Multiline) == RegexOptions.Multiline)
			{
				options.Add("RegexOptions.Multiline");
			}

			if ((regex.Options & RegexOptions.ExplicitCapture) == RegexOptions.ExplicitCapture)
			{
				options.Add("RegexOptions.ExplicitCapture");
			}

			if ((regex.Options & RegexOptions.Compiled) == RegexOptions.Compiled)
			{
				options.Add("RegexOptions.Compiled");
			}

			if ((regex.Options & RegexOptions.Singleline) == RegexOptions.Singleline)
			{
				options.Add("RegexOptions.Singleline");
			}

			if ((regex.Options & RegexOptions.IgnorePatternWhitespace) == RegexOptions.IgnorePatternWhitespace)
			{
				options.Add("RegexOptions.IgnorePatternWhitespace");
			}

			if ((regex.Options & RegexOptions.RightToLeft) == RegexOptions.RightToLeft)
			{
				options.Add("RegexOptions.RightToLeft");
			}

			if ((regex.Options & RegexOptions.ECMAScript) == RegexOptions.ECMAScript)
			{
				options.Add("RegexOptions.ECMAScript");
			}

			if ((regex.Options & RegexOptions.CultureInvariant) == RegexOptions.CultureInvariant)
			{
				options.Add("RegexOptions.CultureInvariant");
			}

			if (options.Count > 0)
			{
				return options.JoinStrings("|");
			}
			else
			{
				return "RegexOptions.None";
			}
		}

		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{

			SavedSettings saved = new SavedSettings
			{
				RegexOptions = RegexV.RegexOptions,
				RegexStr = RegexV.RegexString,
				Source = SourceV.TextBox.Text
			};

			saved.Save(SettingsFilepath);
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			SavedSettings saved = SavedSettings.Load(SettingsFilepath);
			if (saved == null)
			{
				return;
			}
			RegexV.SetRegex(saved.RegexStr, saved.RegexOptions);
			SourceV.TextBox.Text = saved.Source;
		}

		private void Grid_ReplacerButtonClick(object sender, RoutedEventArgs e)
		{
			ReplacerView rv = e.OriginalSource as ReplacerView;
			if (rv == null)
			{
				throw new ApplicationException(string.Format("Error.  ReplacerButtonClick event was passed a sender of type '{0}', expected type '{1}'", sender.GetType(),
					typeof(ReplacerView)));
			}

			processReplaceFunction(rv);
		}

		private void processReplaceFunction(ReplacerView rv)
		{
			rv.ProcessReplace(RegexV.RegexString, RegexV.RegexOptions, SourceV.SrcTB.Text);
		}

		private void FromCSBTN_Click(object sender, RoutedEventArgs e)
		{
			ImportDialog id = new ImportDialog();
	
			if (id.ShowDialog() == true)
			{
				RegexV.SetRegex(id.ImportedString, RegexOptions.None);
			}
		}

		private string getCSharpCodeFromRegex(string regexStr, RegexOptions options)
		{
			try
			{
				Regex re = new Regex(regexStr, options);
				return getCSharpCodeFromRegex(re);
			}
			catch (Exception e)
			{
				MessageBox.Show(string.Format("Error.  Current Regex string cannot be compiled:\r\n{0}", e), "Error exporting Regex");
				return null;
			}
		}
		
		private string getCSharpCodeFromRegex(Regex regex)
		{
			StringBuilder sb = new StringBuilder();

			string escaped = regex.ToString().Replace("\"", "\"\"");
			string options = getOptionsAsString(regex);
			sb.AppendFormat("string reStr = @\"{0}\";\r\n", escaped);
			sb.AppendFormat("Regex re = new Regex(reStr, {0});\r\n", options);

			return sb.ToString();

		}
	}
}
